/*
*  Copyright (c) 2006-2020, Chukie
*  
*  SPDX-License-Identifier: Apache-2.0
*  
*  @file     : uart_frame.h
*  
*  @brief    : 
*  
*  
*  Change Logs:
*  Date           Author          Notes
*  2020-09-19     zhaocj          the first version
*  2021-06-17     zhaocj          删除发送线程。由于应用层可能发送较大的数据，
*                                  发送线程的缓冲区可能无法存放较大的数据,
*                                 因此删除发送线程,应用层只接调用设备接口发送数据
*/

/* Define to prevent recursive inclusion ------------------------------------*/
#ifndef __UART_FRAME_H__
#define __UART_FRAME_H__
/* Includes -----------------------------------------------------------------*/
#include <rtthread.h>
#include <rtdevice.h>
/* Exported types -----------------------------------------------------------*/

#ifndef UART_FRAME_THREAD_PRIO
#define UART_FRAME_THREAD_PRIO   1
#endif /*UART_FRAME_THREAD_PRIO*/

#ifndef UART_FRAME_THREAD_STACK_SIZE
#define UART_FRAME_THREAD_STACK_SIZE            1536
#endif /*UART_FRAME_THREAD_STACK_SIZE*/

#ifndef UART_FRAME_RX_CACHE_MIN_SIZE
#define UART_FRAME_RX_CACHE_MIN_SIZE   1024
#endif /*UART_FRAME_RX_CACHE_MIN_SIZE*/

#ifndef UART_FRAME_RX_MIN_BLK_NUM
#define UART_FRAME_RX_MIN_BLK_NUM   8
#endif /*UART_FRAME_RX_MIN_BLK_NUM*/

#ifndef UART_FRAME_RX_MIN_BUF_SIZE
#define UART_FRAME_RX_MIN_BUF_SIZE      4096
#endif /*UART_FRAME_RX_MIN_BUF_SIZE*/

#ifndef UART_FRAME_DEFAULT_RX_FRAME_SIZE
#define UART_FRAME_DEFAULT_RX_FRAME_SIZE    1024
#endif /*UART_FRAME_DEFAULT_RX_FRAME_SIZE*/

#ifndef UART_FRAME_DEFAULT_RX_FRAME_INTERVALE
#define UART_FRAME_DEFAULT_RX_FRAME_INTERVALE   200
#endif /*UART_FRAME_DEFAULT_RX_FRAME_INTERVALE*/


struct uart_frame_config
{
    struct serial_configure serial_cfg;
    uint32_t rx_cache_size;
    uint32_t rx_buffer_size : 24;
    uint32_t rx_block_num : 8;
    
    /*最大帧长度,连续接收数据达到该长度会导致分帧*/
    uint32_t max_frame_size:16;
    /*帧间隔,单位ms,连续超过该间隔没收到数据认为被当做一帧*/
    uint32_t interval_ms:16;
};
typedef struct uart_frame_config* uart_frame_config_t;

struct uart_frame_statistics
{
    rt_uint32_t rx_bytes;
    rt_uint32_t rx_dropped;
    rt_uint32_t tx_bytes;
    rt_uint32_t tx_dropped;
};
typedef struct uart_frame_statistics* uart_frame_statistics_t;

typedef struct uart_instance* uart_instance_t;
typedef int (*uart_frame_input_hook)(uart_instance_t instance, uint8_t *data, size_t len);
struct uart_instance{
    rt_bool_t running;
    struct rt_thread thread;
    struct rt_semaphore rx_sem;
    struct rt_semaphore tx_sem;
    struct rt_mutex tx_lock;
    rt_rbb_t rbb;
    rt_uint8_t stack[UART_FRAME_THREAD_STACK_SIZE];

    /*串口设备*/
    rt_device_t device;
    struct uart_frame_config config;
    struct uart_frame_statistics stat;
    uart_frame_input_hook input_hook;

    /*缓存*/
    uint8_t *rx_cache_buf;
    rt_slist_t list;
};
/* Exported constants -------------------------------------------------------*/

/* Exported macro -----------------------------------------------------------*/
#define UART_FRAME_DEFAULT_CONFIG \
{ \
    .serial_cfg = RT_SERIAL_CONFIG_DEFAULT, \
    .rx_cache_size = UART_FRAME_RX_CACHE_MIN_SIZE, \
    .rx_buffer_size = UART_FRAME_RX_MIN_BUF_SIZE, \
    .rx_block_num = UART_FRAME_RX_MIN_BLK_NUM, \
    .max_frame_size = UART_FRAME_DEFAULT_RX_FRAME_SIZE, \
    .interval_ms = UART_FRAME_DEFAULT_RX_FRAME_INTERVALE, \
}
/* Exported functions -------------------------------------------------------*/
/**
 * @brief Initialize a uart frame instance,and start it
 * 
 * @param instance uart frame instance,reference to uart_instance_t
 * @param dev_name devcie name
 * @param config   uart frame instance,refernce to uart_frame_config_t
 * @param hook     user hook that will be call when receive data from device
 * @return int  
 *              RT_EOK: success
 *              !RT_EOK: failed
 */
int uart_frame_init(uart_instance_t instance,const char *dev_name,uart_frame_config_t config,
    uart_frame_input_hook hook);

/**
 * @brief create uart frame instance
 * 
 * @param dev_name 
 * @param config 
 * @param hook 
 * @return uart_instance_t 
 */
uart_instance_t uart_frame_create(const char *dev_name, uart_frame_config_t config,
                    uart_frame_input_hook hook);

/**
 * @brief 
 * 
 * @param instance uart frame instance,reference to uart_instance_t
 * @param buf 
 * @param buf_size 
 * @return int 
 */
int uart_frame_read(uart_instance_t instance, uint8_t *buf,size_t buf_size);

/**
 * @brief flush received data
 * 
 * @param instance 
 * @param buf 
 * @param buf_size 
 * @return int 
 */
int uart_frame_flush(uart_instance_t instance, uint8_t *buf, size_t buf_size);

/**
 * @brief write data to tx buffer
 * 
 * @param instance uart frame instance,reference to uart_instance_t
 * @param data data to be sent
 * @param len   data length
 * @return int 
 *          >0 : the data length saved in tx buffer
 *          <0: error
 */
int uart_frame_write(uart_instance_t instance, uint8_t *data,size_t len);
#endif /*__UART_FRAME_H__*/
/* End of file****************************************************************/

